package com.evaluation.util;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.UrlPathHelper;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;


/**
 * HttpServletRequest帮助类
 * 
 * @author liufang
 * 
 */
@Slf4j
public class RequestUtils {

	/**
	 * 获得本机实际IP
	 * @return
	 * @throws Exception
	 */
	public static String[] getLocalHostLANAddress() {
		String[] ipInfos = new String[2];

		try {
			InetAddress candidateAddress = null;
			// 遍历所有的网络接口
			for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
				NetworkInterface iface = ifaces.nextElement();
				// 在所有的接口下再遍历IP
				for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
					InetAddress inetAddr = inetAddrs.nextElement();
					if (!inetAddr.isLoopbackAddress()) {// 排除loopback类型地址
						if (inetAddr.isSiteLocalAddress()) {
							// 如果是site-local地址，就是它了
							ipInfos[0] = inetAddr.getHostAddress();
							ipInfos[1] = inetAddr.getHostName();
							return ipInfos;
						} else if (candidateAddress == null) {
							// site-local类型的地址未被发现，先记录候选地址
							candidateAddress = inetAddr;
						}
					}
				}
			}
			if (candidateAddress != null) {
				ipInfos[0] = candidateAddress.getHostAddress();
				ipInfos[1] = candidateAddress.getHostName();
				return ipInfos;
			}
			// 如果没有发现 non-loopback地址.只能用最次选的方案
			InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
			ipInfos[0] = jdkSuppliedAddress.getHostAddress();
			ipInfos[1] = jdkSuppliedAddress.getHostName();
		} catch (Exception e) {
			e.printStackTrace();
			ipInfos[0] = "127.0.0.1";
			ipInfos[1] = "localhost";
		}
		return ipInfos;
	}

	
	/**
	 * 
	 * Parses a query string passed from the client to the server and builds a
	 * <code>HashTable</code> object with key-value pairs. The query string
	 * should be in the form of a string packaged by the GET or POST method,
	 * that is, it should have key-value pairs in the form <i>key=value</i>,
	 * with each pair separated from the next by a &amp; character.
	 * 
	 * <p>
	 * A key can appear more than once in the query string with different
	 * values. However, the key appears only once in the hashtable, with its
	 * value being an array of strings containing the multiple values sent by
	 * the query string.
	 * 
	 * <p>
	 * The keys and values in the hashtable are stored in their decoded form, so
	 * any + characters are converted to spaces, and characters sent in
	 * hexadecimal notation (like <i>%xx</i>) are converted to ASCII characters.
	 * 
	 * @param s
	 *            a string containing the query to be parsed
	 * 
	 * @return a <code>HashTable</code> object built from the parsed key-value
	 *         pairs
	 * 
	 * @exception IllegalArgumentException
	 *                if the query string is invalid
	 * 
	 */
	public static Map<String, String[]> parseQueryString(String s) {
		Map<String, String[]> ht = null;
		String valArray[] = null;
		if (s == null) {
			throw new IllegalArgumentException();
		}
		ht = new HashMap<String, String[]>();
		StringTokenizer st = new StringTokenizer(s, "&");
		while (st.hasMoreTokens()) {
			String pair = (String) st.nextToken();
			int pos = pair.indexOf('=');
			if (pos == -1) {
				continue;
			}
			String key = pair.substring(0, pos);
			String val = pair.substring(pos + 1, pair.length());
			if (ht.containsKey(key)) {
				String oldVals[] = (String[]) ht.get(key);
				valArray = new String[oldVals.length + 1];
				for (int i = 0; i < oldVals.length; i++) {
					valArray[i] = oldVals[i];
				}
				valArray[oldVals.length] = val;
			} else {
				valArray = new String[1];
				valArray[0] = val;
			}
			ht.put(key, valArray);
		}

		return ht;
	}


	@Deprecated
	public static String getIpAddress2(HttpServletRequest request) {

		String ip = request.getHeader("x-forwarded-for");
log.info("ip:{}", ip);
		String localIP = "127.0.0.1";

		if ((ip == null) || (ip.length() == 0) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
			log.info("ip:{}", ip);
		}
		if ((ip == null) || (ip.length() == 0) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
			log.info("ip:{}", ip);
		}
		if ((ip == null) || (ip.length() == 0) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
			log.info("ip:{}", ip);
		}
		return ip;
	}

	public final static String getIpAddress(HttpServletRequest request) {

	    // 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址  
	    String ip = request.getHeader("X-Forwarded-For");
	    if (log.isDebugEnabled()) {
	    	log.info("getIpAddress(HttpServletRequest) - X-Forwarded-For - String ip=" + ip);
	    }

	    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	            ip = request.getHeader("Proxy-Client-IP");
	            if (log.isDebugEnabled()) {
	            	log.info("getIpAddress(HttpServletRequest) - Proxy-Client-IP - String ip=" + ip);
	            }
	        }
	        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	            ip = request.getHeader("WL-Proxy-Client-IP");
	            if (log.isDebugEnabled()) {
	            	log.info("getIpAddress(HttpServletRequest) - WL-Proxy-Client-IP - String ip=" + ip);
	            }
	        }
	        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	            ip = request.getHeader("HTTP_CLIENT_IP");
	            if (log.isDebugEnabled()) {
	            	log.info("getIpAddress(HttpServletRequest) - HTTP_CLIENT_IP - String ip=" + ip);
	            }
	        }
	        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
	            if (log.isDebugEnabled()) {
	            	log.info("getIpAddress(HttpServletRequest) - HTTP_X_FORWARDED_FOR - String ip=" + ip);
	            }
	        }
	        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	            ip = request.getRemoteAddr();
	            if (log.isDebugEnabled()) {
	            	log.info("getIpAddress(HttpServletRequest) - getRemoteAddr - String ip=" + ip);
	            }
	        }
	    } else if (ip.length() > 15) {
	        String[] ips = ip.split(",");
	        for (int index = 0; index < ips.length; index++) {
	            String strIp = (String) ips[index];
	            if (! ("unknown".equalsIgnoreCase(strIp))) {
	                ip = strIp;
	                break;
	            }
	        }
	    }
	    return ip;
	}
	
	/**
	 * 获得当的访问路径
	 * 
	 * HttpServletRequest.getRequestURL+"?"+HttpServletRequest.getQueryString
	 * 
	 * @param request
	 * @return
	 */
	public static String getLocation(HttpServletRequest request) {
		StringBuffer buff = null;
		UrlPathHelper helper = new UrlPathHelper();
		buff = request.getRequestURL();
		String uri = request.getRequestURI();
		String origUri = helper.getOriginatingRequestUri(request);
		buff.replace(buff.length() - uri.length(), buff.length(), origUri);
		String queryString = helper.getOriginatingQueryString(request);
		if (queryString != null) {
			buff.append("?").append(queryString);
		}
		return buff.toString();
	}


	/**
	 * 取请求文件的路径，本来可以request.getServletPath(),但是weblogic有bug不支持此函数
	 * 
	 * @param request
	 * @return
	 */
	public static String getPath(HttpServletRequest request) {
		String path = request.getPathInfo();
		if (path == null){
			return request.getServletPath();
		}
		return path;
	}

	public static boolean isAjax(HttpServletRequest request) {

		// HttpServletRequest request =
		// ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();

		/*
		 * Enumeration<String> em = request.getHeaderNames(); while(
		 * em.hasMoreElements() ) { String key = em.nextElement(); System.out.println(
		 * key+"="+request.getHeader(key) ); }
		 */

		// request.getHeader("x-requested-with")

		/// System.out.println( request.getHeader("x-requested-with") );

		if (request.getHeader("x-requested-with") != null && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
			return true;
		}

		return false;
	}

	public static boolean isAjax() {

		ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		if( servletRequestAttributes == null ) {
			return false;
		}
		
		HttpServletRequest request = servletRequestAttributes.getRequest();

		return isAjax(request);
	}

	public static boolean isRestRequest(HttpServletRequest request) {

		String contentType = request.getContentType();

		return isAjax(request) || (StringUtils.hasLength(contentType) && contentType.indexOf("application/") >= 0);
	}

	public static String getHeaderTokenId() {

		return getHeader("insure-tk");

	}

	public static String getHeader(String name) {
		ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		if( servletRequestAttributes == null ) {
			return "";
		}
		
		HttpServletRequest request = servletRequestAttributes.getRequest();

		return request.getHeader(name);

	}
	
	/**
	 * 检查Session失效后是不是Rest风格的请求
	 * @param request
	 * @param response
	 * @return
	 */
	public static boolean checkSessionInvalidateForRest( HttpServletRequest request, int state, String message ) {
		if( RequestUtils.isRestRequest(request) ) {
    		Map<String, Object> map = new HashMap<>();
    		
    		map.put("state", state);
    		map.put("resCode", String.valueOf(state));
    		map.put("result", message);	//"登录超时,请重新登录"
    		map.put("success", false);
    		request.getSession().invalidate();
    		try {
				ResponseUtils.sendToClient( map );
			} catch (Exception e) {
				e.printStackTrace();
			}
    		
    		return false;
    	}
		return true;
	}
}
